package api

import (
	"buding-ai/internal/core"
	"buding-ai/internal/repository/model"
	"buding-ai/internal/web/dto"
	"buding-ai/internal/web/response"
	"buding-ai/pkg/utils/snowflake"
	"buding-ai/pkg/vec"
	"fmt"
	"github.com/gin-gonic/gin"
	"math"
	"strconv"
)

type KnowledgeApi struct {
	group *gin.RouterGroup
}

func NewKnowledgeApi(group *gin.RouterGroup) *KnowledgeApi {
	chat := &KnowledgeApi{
		group: group,
	}
	group.POST("/add", chat.Add)
	group.GET("/list", chat.List)
	group.DELETE("/delete", chat.Delete)
	return chat
}

func (a KnowledgeApi) Add(ctx *gin.Context) {
	var create dto.KnowledgeCreateDTO
	var err error
	if err = ctx.ShouldBindJSON(&create); err != nil {
		response.ParamBindError(ctx, err)
		return
	}

	// 根据问题查询是否已存在
	var existingKnowledge model.Knowledge
	result := core.DB.Where("question = ?", create.Question).First(&existingKnowledge)
	if result.RowsAffected > 0 {
		// 找到相同问题的记录，返回已存在提示
		response.Success(ctx, "该问题已存在", existingKnowledge)
		return
	}

	// 创建知识实体
	knowledge := model.NewKnowledge(create.Question, create.Answer, 1)
	// 保存向量数据
	if err = a.saveVec(create, knowledge); err != nil {
		response.InternalError(ctx, "保存向量数据失败", err)
		return
	}

	// 更新数据库记录
	if err = core.DB.Save(knowledge).Error; err != nil {
		response.InternalError(ctx, "更新知识向量ID失败", err)
		return
	}

	response.Success(ctx, "添加成功", knowledge)
}

func (a KnowledgeApi) saveVec(create dto.KnowledgeCreateDTO, knowledge *model.Knowledge) error {
	var err error
	var answerEmbedding []float32
	var questionEmbedding []float32
	var questionId int64
	var answerId int64
	qCollectionName := "knowledge"

	// 构建问题的向量payload
	payload := map[string]interface{}{
		"question": create.Question,
		"answer":   create.Answer,
		"type":     "question",
	}

	// 存储问题向量到Qdrant
	questionEmbedding, err = vec.GetTongYiEmbedding(create.Question)
	if err != nil {
		return fmt.Errorf("生成答案向量失败: %v", err)
	}
	questionId, err = snowflake.SF.NextID()
	if err != nil {
		return fmt.Errorf("生成问题ID失败: %v", err)
	}
	err = vec.Client.AddPoint(qCollectionName, uint64(questionId), questionEmbedding, payload)
	if err != nil {
		return fmt.Errorf("保存问题向量失败: %v", err)
	}
	knowledge.QVectorId = questionId

	// 存储答案向量到Qdrant
	if !create.SerializeAnswer {
		return nil
	}
	answerEmbedding, err = vec.GetTongYiEmbedding(create.Question)
	if err != nil {
		return fmt.Errorf("生成答案向量失败: %v", err)
	}
	answerId, err = snowflake.SF.NextID()
	if err != nil {
		return fmt.Errorf("生成答案ID失败: %v", err)
	}
	payload["type"] = "answer"
	err = vec.Client.AddPoint(qCollectionName, uint64(answerId), answerEmbedding, payload)
	if err != nil {
		return fmt.Errorf("保存答案向量失败: %v", err)
	}
	knowledge.AVectorId = answerId
	return nil
}

func (a KnowledgeApi) List(ctx *gin.Context) {
	var knowledgeList []model.Knowledge
	var err error
	var total int64

	// 获取分页参数
	page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(ctx.DefaultQuery("pageSize", "100"))
	search := ctx.Query("search")
	// 防止非法参数
	if page < 1 {
		page = 1
	}
	if pageSize < 1 || pageSize > 100 {
		pageSize = 100
	}

	// 计算分页偏移量
	offset := (page - 1) * pageSize

	// 获取查询参数

	query := core.DB.Model(&model.Knowledge{})

	// 如果有搜索关键词，添加模糊查询条件
	if search != "" {
		searchTerm := "%" + search + "%"
		query = query.Where("question LIKE ? OR answer LIKE ?", searchTerm, searchTerm)
	}

	// 计算总数
	if err = query.Count(&total).Error; err != nil {
		response.InternalError(ctx, "计算知识库总数失败", err)
		return
	}

	// 分页查询数据
	if err = query.Order("created_at DESC").Offset(offset).Limit(pageSize).Find(&knowledgeList).Error; err != nil {
		response.InternalError(ctx, "获取知识库列表失败", err)
		return
	}

	// 构建分页响应数据
	result := gin.H{
		"items":     knowledgeList,
		"total":     total,
		"page":      page,
		"pageSize":  pageSize,
		"totalPage": int(math.Ceil(float64(total) / float64(pageSize))),
	}

	// 返回成功响应
	response.SuccessWithData(ctx, result)
}

func (a KnowledgeApi) Delete(ctx *gin.Context) {
	// 获取知识ID参数
	idStr := ctx.Query("id")
	id, err := strconv.ParseUint(idStr, 10, 64)
	if err != nil {
		response.ParamError(ctx, "无效的知识ID")
		return
	}

	// 查询知识条目
	var knowledge model.Knowledge
	if err := core.DB.First(&knowledge, id).Error; err != nil {
		response.NotFound(ctx, "知识条目不存在")
		return
	}

	// 删除向量库中的向量
	qCollectionName := "knowledge"
	// 删除问题向量
	if knowledge.QVectorId > 0 {
		if err := vec.Client.DeletePoint(qCollectionName, uint64(knowledge.QVectorId)); err != nil {
			response.InternalError(ctx, "删除问题向量失败", err)
			return
		}
	}

	// 删除答案向量（如果存在）
	if knowledge.AVectorId > 0 {
		if err := vec.Client.DeletePoint(qCollectionName, uint64(knowledge.AVectorId)); err != nil {
			response.InternalError(ctx, "删除答案向量失败", err)
			return
		}
	}

	// 删除知识条目
	if err := core.DB.Delete(&knowledge).Error; err != nil {
		response.InternalError(ctx, "删除知识条目失败", err)
		return
	}

	response.Success(ctx, "删除成功", nil)
}
